package com.code2roc.xhood.asm;

import com.code2roc.xhood.model.ClassParentInfo;
import com.code2roc.xhood.model.ObsureEnum;
import com.code2roc.xhood.util.ObscureUtil;
import org.apache.commons.lang3.StringUtils;
import org.objectweb.asm.*;

import java.util.HashMap;
import java.util.List;

public class FieldInvokeAdapter extends MethodVisitor {
    private List<String> refreshList;
    private String outPutPath;

    public FieldInvokeAdapter(MethodVisitor methodVisitor, List<String> refreshList, String outPutPath) {
        super(Opcodes.ASM9, methodVisitor);
        this.refreshList = refreshList;
        this.outPutPath = outPutPath;
    }

    @Override
    public void visitFieldInsn(int opcode, String owner, String name, String descriptor) {
        String className = owner.replace("/", ".");
        String fieldName = owner.replace("/", ".") + "." + name;
        boolean flag = false;
        if (refreshList.contains(fieldName)) {
            flag = true;
        }else{
            ClassParentInfo info = ObscureUtil.getClassExtendAndInterfaceInfo(outPutPath, owner.replace("/", "."));
            if (StringUtils.isNotEmpty(info.getSuperName())) {
                HashMap<String, String> paramMap = new HashMap();
                String obfuscatedName = ObscureUtil.getObscureNameV3(className,name, ObsureEnum.Field);
                ObscureUtil.findAllParentField(outPutPath, obfuscatedName, descriptor, info.getSuperName(), paramMap);
                for (String interfaceName : info.getInterfaceList()) {
                    ObscureUtil.findAllParentField(outPutPath, obfuscatedName, descriptor, interfaceName, paramMap);
                }
                for (String value : paramMap.values()) {
                    String key = value + "." + name;
                    if (refreshList.contains(key)) {
                        flag = true;
                        break;
                    }
                }
            }
        }
        if(flag){
            String obfuscatedName = ObscureUtil.getObscureNameV3(className,name, ObsureEnum.Field);
            super.visitFieldInsn(opcode, owner, obfuscatedName, descriptor);
        }else{
            super.visitFieldInsn(opcode, owner, name, descriptor);
        }
    }
}
